#pragma once

#include <compl.h>
#include <ddblk/adep_dblk.h>
#include <ddblk/apds/apds_def.h>
#include <ddblk/apds/apds_hdef.h>
#include <ddblk/apds/apds_tinfo.h>
#include <ddblk/apds/lockyield.h>

/* COMBINE的一些定义 */
#define COMBINE_FLG_WAIT		(0)
#define COMBINE_FLG_OWNED		(1)
#define COMBINE_FLG_COMPLETED		(2)

#define COMBINE_TEFF(cid_eff)		word_high(cid_eff)
#define COMBINE_TCID(cid_eff)		word_low(cid_eff)

/* 定义依赖wait策略 */
OU2INFUN(blkwait, cmbn_wait)

/* 分配策略 */
OU2INFUN(lknode, cmbn_node)

/* 应该要和节点分配器解耦合: 内部解耦合 */
/* 定义combine接口 */
/* 接受两种策略 */
/* 接口分别是 comb初始化 */
/* comb解构 */
#define DECL_COMBINE(cmbnname)				\
SAI _##cmbnname##_t *_##cmbnname##_init(void *ptr, size_t size, INFUN(cmbn_node, nodemgr));\
SAI void *_##cmbnname##_destruct(_##cmbnname##_t *s, INFUN(cmbn_node, nodemgr));\
SAI _##cmbnname##node_t *_##cmbnname##_fetch(_##cmbnname##_t *s, apdsfunc_t *pfunc, apdsarg_t *args, apdstinfo_t *tinfo, INFUN(cmbn_node, nodemgr));\
SAI apdsret_t _##cmbnname##_wait(_##cmbnname##_t *s, _##cmbnname##node_t *node, \
	apdstinfo_t *tinfo, INFUN(cmbn_wait, waitpolicy), INFUN(cmbn_node, nodemgr));\



#define DEF_COMBINE(cmbnname, name, ptinfo, pblkwait, plknode)	\
typedef _##cmbnname##_t name##_t;\
typedef _##cmbnname##node_t name##node_t;\
SIN apds_t* name##_init (void *ptr, size_t size){ return _##cmbnname##_init(ptr, size, plknode); }	\
SIN void* name##_destruct (apds_t *l){ return _##cmbnname##_destruct((_##cmbnname##_t *)l, plknode); }	\
SAI apdsfuture_t* name##_fetch (apds_t *l, apdsfunc_t *pfunc, apdsarg_t *args){ (ptinfo)->upd(); return (apdsfuture_t *)_##cmbnname##_fetch((_##cmbnname##_t *)l, pfunc, args, (ptinfo)->get(), plknode); }\
SAI apdsret_t name##_wait (apds_t *l, apdsfuture_t *f){ \
	apdsret_t ret = _##cmbnname##_wait((_##cmbnname##_t *)l, (_##cmbnname##node_t *)f, (ptinfo)->get(), pblkwait, plknode); \
	/*(ptinfo)->upd();*/ \
	return ret; }\
SAI apdsret_t name##_sync (apds_t *l, apdsfunc_t *pfunc, apdsarg_t *args){				\
	apdstinfo_t *pinfo = (ptinfo)->get();								\
	apdsret_t ret;											\
	(ptinfo)->upd();										\
	_##cmbnname##node_t *p = _##cmbnname##_fetch((_##cmbnname##_t *)l, pfunc, args, pinfo, plknode);\
	ret = _##cmbnname##_wait((_##cmbnname##_t *)l, p, (ptinfo)->get(), pblkwait, plknode);		\
	return ret;											\
}\
NEW_OUFUN(apds, name, name##_init, name##_destruct, name##_fetch, name##_wait, name##_sync)
